#ifndef __MVT_SDB_H__
#define __MVT_SDB_H__

#include <pthread.h>

#include "mvdef.h"
#include "mvos/mvos_apis.h"

/** ！！！vmidx对应数据结构顺序一旦设定，只允许追加，否则会导致db数据结构异常 */
/** ！！！sdb的page大小一旦设定，不允许更改，否则会导致db数据结构异常 */

#define DB_PAGE_DEFAULT_SZ  4*1024  //4K页
typedef struct _sdb
{
	mv_v8_t      av8_db_path[256];
	mv_size_t    sz_page;          /* idx page size (S.P. 0=default) 一旦设定，不要改动！！！ */
	/* internal using, don't change */
    mvos_mutex_t file_lock; 
	mv_s32_t     fd_tmp;
}mvt_sdb_t;

typedef struct _sdb_node
{
    mv_vptr_t       p_entry;
	mv_u8_t         u8_dbidx;   /* witch db to be storage in    ([0,255]*/
    mv_u8_t         u8_stidx;   /* virtual memory storage index ([1,255] , 0=don't storage) */
    mv_u8_t         u8_gen;     /* attr generation */
    mv_s32_t        s32_len;
	/* internal using, don't change */
    mvos_mutex_t    mutex_lock; 
}mvt_sdb_node_t;

#define MVT_VM_IDX(dbidx, stidx)  ((dbidx&0xff)<<8)|(stidx&0xff)
#define MVT_DB_IDX(vmidx)         ((vmidx>>8)&0xff)
#define MVT_ST_IDX(vmidx)          (vmidx&0xff)
#define MVT_DB_NODE(pstru_attr, vmidx, T) {.p_entry=pstru_attr, .u8_dbidx=MVT_DB_IDX(vmidx), .u8_stidx=MVT_ST_IDX(vmidx), .u8_gen=0, .s32_len=sizeof(T)}

/** success: MV_EC_SUCCESS; failed: MV_EC_NOT_MATCH */
typedef mv_s32_t(*pf_md5_cal)(mv_u8ptr_t pu8_md5_output, mv_cu8ptr_t cpu8_data, mv_s32_t s32_len);

typedef struct _sdb_handle
{
	mv_s32_t        s32_db_num;
	mv_s32_t        s32_db_node_num;
	mvt_sdb_t      *astru_db_list;
	mvt_sdb_node_t *astru_db_node_tb;
	pf_md5_cal      f_md5_cal;       ///< NULL means not check
	mv_u8_t         u8_inited;
}mvt_sdb_handle_t;

/**
 * @brief SDB句柄初始化
 * 
 * @param phdl [in] sdb句柄
 * @return 初始化结果
 * - success : MV_EC_SUCCESS
 * -  failed : else (<0)
 */
mv_s32_t   mvt_sdb_init  (mvt_sdb_handle_t *phdl);
/**
 * @brief DB重载(对配置了stidx的节点有效)
 * 
 * @param phdl      [in] sdb句柄
 * @param s32_vmidx [in] 重载目标vmidx
 * @return 重载结果
 * - success : MV_EC_SUCCESS
 * -  failed : else (<0)
 * 
 * @note 支持db_list全重载（vmidx=-1）
 * @note 支持db单个全重载(vmidx=MVT_VM_IDX(N, 0))
 * @note 支持db目标项重载(vmidx=MVT_VM_IDX(N, M), M非0)
 */
mv_s32_t   mvt_sdb_reload(mvt_sdb_handle_t *phdl, mv_s32_t s32_vmidx);
/**
 * @brief DB节点引用
 * 
 * @param phdl     [in] sdb句柄
 * @param u32_nidx [in] [astru_db_node_tb]DB节点列表下标
 * @param p_nmem   [in] 输出缓冲区（安全引用）
 * @return DB节点缓存数据地址 
 */
mv_cvptr_t mvt_sdb_node_get   (mvt_sdb_handle_t *phdl, mv_u32_t u32_nidx, mv_vptr_t p_nmem);
/** @param pu8_gen [out] 取出当前节点数据generation id */
mv_cvptr_t mvt_sdb_node_get_ex(mvt_sdb_handle_t *phdl, mv_u32_t u32_nidx, mv_vptr_t p_nmem, mv_u8ptr_t pu8_gen);
/**
 * @brief DB节点数据更新
 * 
 * @param phdl     [in] sdb句柄
 * @param u32_nidx [in] [astru_db_node_tb]DB节点列表下标
 * @param p_nmem   [in] 待更新数据
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : else(<0) 
 */
mv_s32_t   mvt_sdb_node_set   (mvt_sdb_handle_t *phdl, mv_u32_t u32_nidx, mv_vptr_t p_nmem);
/**
 * @brief DB节点数据更新（线程安全）
 * 
 * @param phdl      [in] sdb句柄
 * @param u32_nidx  [in] [astru_db_node_tb]DB节点列表下标
 * @param f_modify  [in] 数据修改回调
 * @param p_usrdata [in] 回调自定义入参数据
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : else(<0) 
 * @attention f_modify 返回非MV_EC_SUCCESS时，不会更新DB数据，但是要注意过程中被修改的缓存不会恢复！
 */
mv_s32_t   mvt_sdb_node_set_r(mvt_sdb_handle_t *phdl, mv_u32_t u32_nidx, mv_s32_t(*f_modify)(mv_vptr_t p_nmem, mv_vptr_t p_usrdata), mv_vptr_t p_usrdata);

/**
 * @brief DB节点数据写引用（线程安全，分离式调用的起手式）
 * 
 * @param phdl      [in] sdb句柄
 * @param u32_nidx  [in] [astru_db_node_tb]DB节点列表下标
 * @param p_nmem    [in] 输出缓冲区
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : else(<0) 
 * @attention 当引用成功时，该DB节点就会被锁上，需要对应调用mvt_sdb_node_wuref释放才能被其他人引用
 */
mv_s32_t   mvt_sdb_node_wref(mvt_sdb_handle_t *phdl, mv_u32_t u32_nidx, mv_vptr_t p_nmem);
/**
 * @brief DB节点数据写释放（线程安全，分离式调用的结束式）
 * 
 * @param phdl      [in] sdb句柄
 * @param u32_nidx  [in] [astru_db_node_tb]DB节点列表下标
 * @param p_nmem    [in] 更新数据
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : else(<0) 
 * @attention 必须跟mvt_sdb_node_wref匹配调用；不管返回结果如何，都会解除对DB节点的写引用
 */
mv_s32_t   mvt_sdb_node_wuref(mvt_sdb_handle_t *phdl, mv_u32_t u32_nidx, mv_vptr_t p_nmem);

#endif